package com.quantstack.llcommonlibrary.base;

import android.text.TextUtils;

import com.google.gson.JsonParseException;
import com.quantstack.llcommonlibrary.utils.LogUtils;

import org.json.JSONException;

import java.io.InterruptedIOException;
import java.lang.reflect.Field;
import java.net.ConnectException;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import io.reactivex.observers.DisposableObserver;
import retrofit2.HttpException;

/**
 * File descripition:   数据处理基类
 *
 * @author lp
 * @date 2018/6/19
 */

public abstract class BaseObserver<T extends BaseHttpResult> extends DisposableObserver<T> {
    protected BaseView view;

    /**
     * 网络连接失败  无网
     */
    public static final int NETWORK_ERROR = 100000;
    /**
     * 解析数据失败
     */
    public static final int PARSE_ERROR = 1008;
    /**
     * 网络问题
     */
    public static final int BAD_NETWORK = 1007;
    /**
     * 连接错误
     */
    public static final int CONNECT_ERROR = 1006;
    /**
     * 连接超时
     */
    public static final int CONNECT_TIMEOUT = 1005;
    /**
     * 非 true的所有情况
     */
    public static final int NOT_TRUE_OVER = 1004;


    public BaseObserver(BaseView view) {
        this.view = view;
    }

    public BaseObserver() {

    }


    @Override
    protected void onStart() {
        if (view != null) {
            view.showLoadingDialog("loading...");
        }
    }

    @Override
    public void onNext(T o) {
        System.out.println("------->"+o.toString());
        try {
            if (view != null) {
                view.dissMissDialog();
            }
            if(o!=null&&o.getCode()!=0){
                //有错误码
                int errorCode = o.getCode();
                LogUtils.e("错误码-->"+errorCode);
                //非  true的所有情况
                onException(NOT_TRUE_OVER,o.getMsg());
            }else{
                //没有错误码
                Class clz = o.getClass();
                //如果是BaseHttpResult  说明返回的数据不是一个实体类 直接用getData获取
                if(BaseHttpResult.class.equals(clz)){
                    onSuccess(o);
                }else{
                    onSuccess((T) o.getData());
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            onError(e.toString());
        }
    }

    @Override
    public void onError(Throwable e) {
        System.out.println("onError:"+e.getMessage());
        if (view != null) {
            view.dissMissDialog();
        }
        if (e instanceof HttpException) {
            //   HTTP错误
            onException(BAD_NETWORK, "");
        } else if (e instanceof ConnectException
                || e instanceof UnknownHostException) {
            //   连接错误
            onException(CONNECT_ERROR, "");
        } else if (e instanceof InterruptedIOException) {
            //  连接超时
            onException(CONNECT_TIMEOUT, "");
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException) {
            //  解析错误
            onException(PARSE_ERROR, "");
            e.printStackTrace();
        } else {
            if (e != null) {
                onError(e.toString());
            } else {
                onError("network error");
            }
        }

    }

    private void onException(int unknownError, String message) {
        System.out.println("onException:"+message);

        switch (unknownError) {
            case CONNECT_ERROR:
                onError("network error");
                break;
            case CONNECT_TIMEOUT:
                onError("network error");
                break;
            case BAD_NETWORK:
                onError("network error");
                break;
            case PARSE_ERROR:
                onError("network error");
                break;
            //非true的所有情况
            case NOT_TRUE_OVER:
                onError(message);
                break;
            default:
                break;
        }
    }

    //消失写到这 有一定的延迟  对dialog显示有影响
    @Override
    public void onComplete() {
       /* if (view != null) {
            view.hideLoading();
        }*/
    }

    public abstract void onSuccess(T o);

    public abstract void onError(String msg);


    /**
     * 反射判断是否具有某个字段
     * @param c
     * @param fieldName
     * @return
     */
    private boolean hasField(Class c, String fieldName){
        Field[] fields = c.getDeclaredFields();
        Class superclass = c.getSuperclass();//获取父类
        if(superclass!=null){
            Field[] supercFields = superclass.getDeclaredFields();
            for (Field f : supercFields) {
                f.setAccessible(true);
                if (fieldName.equals(f.getName())) {
                    return true;
                }
            }
        }
        for (Field f : fields) {
            f.setAccessible(true);
            if (fieldName.equals(f.getName())) {
                return true;
            }
        }
        return false;
    }

    /**
     * 反射判断是否具有某个字段
     * @param c
     * @param fieldName
     * @return
     */
    public String getFieldValue(Object c, String fieldName){
        try {
            Field field = c.getClass().getField(fieldName);
            // 设置字段可访问， 否则无法访问private修饰的变量值
            field.setAccessible(true);
            String value = (String) field.get(c);
            if(TextUtils.isEmpty(value)){
                Class superclass = c.getClass().getSuperclass();
                if(superclass!=null){
                    Field superField = superclass.getField(fieldName);
                    superField.setAccessible(true);
                    value = (String) superField.get(c);
                }
            }

            return value;
        } catch (Exception e) {
            LogUtils.e("反射异常:"+e.toString());
            return "";
        }
    }



    /**
     * 测试代码
     * @param args
     * @throws IllegalAccessException
     */
    public static void main(String[] args) throws IllegalAccessException {
        List<String> list = new ArrayList<>();
        HashMap<String,String> hashMap = new HashMap<>();
        BaseHttpResult baseHttpResult = new BaseHttpResult();
        Field[] fields = baseHttpResult.getClass().getDeclaredFields();
        for (Field f : fields) {
            System.out.println(f.getName());
            f.setAccessible(true);
            System.out.println(f.get(baseHttpResult));
        }
    }
}
